更新のロスト lost update anomaly
#異常_anomaly
r1[x=A]r2[x=A]w1[x=A +1]w2[x=A+1]c1c2
$ \left[ \begin{array}{cc} T_1 & T_2 \\ r_1[x=A] & \\ & r_2[x=A] \\ w_1[x = A + 1] & \\ & w_2[x = A + 1] \\ c_1 & c_2 \end{array} \right]
A=1だとすると結果x=1となるがトランザクションを別々に実行すればx=2であるはず
「値を読み込んで修正し書き込む」時に起きる
read-modify-writeサイクル
たとえば
wikiのページを更新する
ページごとにカウンタを作ってアクセスあるたびにインクリメントしていく
対応方法
アトミックな操作で行う
update c set v = v + 1 where k = 'key'
wikiのページを更新するとかには使えない
普通アトミックな操作というのは読み取りの際排他ロックをとり更新が適用されるまで他のトランザクションから読めないようにする
カーソル固定 cursor stabilityという
後述するMySQLの場合まさにupdateの際は暗黙的に排他ロックをとっている
明示的にロックをとる
この問題を一般化したのが書き込みスキュー write skew
---.icon
MySQLの場合
MySQLのREPEATABLE READはロッキングリード Locking Readの場合はMVCC(multi-version concurrency control)を使用せずノンロッキングリード non-Locking Readの場合はMVCCを使う
MVCCの場合lost updateを防げないのは教科書通り
ロッキングリードの場合は常に最新の値が読み取られる
つまりノンロッキングリードの場合とは読み取る値が異なる可能性がある
? 一貫性が損なわれているといってもいい